home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / muds / lpmud312.tar / lpmud312 / access_check.c next >
C/C++ Source or Header  |  1993-01-11  |  8KB  |  281 lines

  1. #include <sys/types.h>
  2. #include <sys/time.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5.  
  6. #include "lint.h"
  7. #include "config.h"
  8.  
  9. #ifdef ACCESS_RESTRICTED    /* Comment out whole file */
  10.  
  11. /* check a given internet address against patterns given in an ACCESS.ALLOW
  12.  * file.                       
  13.  * Written by Markus Wild for Loch Ness in 1991.
  14.  * Spread by gec with permission of Markus Wild. 
  15.  * Source is in the public domain. No charges allowed.
  16.  *
  17.  * notice the time stamp when we last scanned the file, and rescan if it
  18.  * changed since that (this enables us to edit the file without having to
  19.  * reboot lpmud to read it)
  20.  * NOTICE: when changing the access file, the old tables ARE DISCARDED. This
  21.  *         means, that users logged in will not count for the per-class
  22.  *         maximum. This will normalize, as soon as users log out, as the
  23.  *         "currently" counter will not go below 0.
  24.  */
  25.  
  26. #include <sys/stat.h>
  27. #include <sys/socket.h>
  28. #include <time.h>
  29. #include <netinet/in.h>
  30. #include <stdio.h>
  31.  
  32. extern char *inet_ntoa(), *strtok();
  33.  
  34. /* this file should better be defined in config.h ;-) */
  35. #define ACCESS_FILE "ACCESS.ALLOW"
  36.  
  37. /* log-file to show valid and rejected connections */
  38. #undef ACCESS_LOG "access.allow.log" /* simply NOT define this for NO logs*/
  39.  
  40. /* maximal string length to be output */
  41. #define MAX_MESSAGE 255
  42.  
  43. struct access_class {
  44.   int class_num;        /* the class number */
  45.   int currently;        /* currently <= this number of logged in users */
  46.   int maximum;            /* 0: disallowed, -1: no maximum */
  47.   char message[MAX_MESSAGE];    /* message to be printed in case a login can't be permitted */
  48. };
  49.  
  50. struct access_address {
  51.   int addr[4];        /* [0..255]: number, -1: all */
  52.   int hstart, hend;    /* start/end hour */
  53.   struct access_class *ac;
  54. };
  55.  
  56. static struct access_address *addr_tab = 0;
  57. static int addr_tab_index, addr_tab_size;
  58. static struct access_class *class_tab = 0;
  59. static int class_tab_index, class_tab_size;
  60. static time_t last_read = 0;
  61.  
  62. static void log_access ();
  63.  
  64. /* check the file, and if it was changed, (re)read it into memory */
  65. static void
  66. check_read_file (name)
  67.      char *name;
  68. {
  69.   struct stat stb;
  70.   FILE *in;
  71.  
  72.   if (!(stat (name, &stb)))
  73.     {
  74.       if (stb.st_mtime > last_read)
  75.     {
  76.       /* throw away the old information */
  77.       if (addr_tab) free ((char *)addr_tab), addr_tab = 0;
  78.       if (class_tab) free ((char *)class_tab), class_tab = 0;
  79.       addr_tab_size = 10;
  80.       addr_tab_index = 0;
  81.       addr_tab = (struct access_address *)
  82.           malloc (addr_tab_size * sizeof (struct access_address));
  83.       class_tab_size = 10;
  84.       class_tab_index = 0;
  85.       class_tab = (struct access_class *)
  86.           malloc (class_tab_size * sizeof (struct access_class));
  87.       
  88.       if (in = fopen (name, "r"))
  89.         {
  90.           while (!feof (in))
  91.         {
  92.           char buffer [2*MAX_MESSAGE]; /* heuristic ;-)) */
  93.           char addr1[4], addr2[4], addr3[4], addr4[4];
  94.           struct access_address aa;
  95.           struct access_class ac;
  96.           char *cp;
  97.           int i;
  98.  
  99.           if (! fgets (buffer, 2*MAX_MESSAGE, in)) break;
  100.           if (buffer[0] == '#') continue; /* a comment, skip */
  101.           /* if there is no ':' in there, this is probably an empty line */
  102.           if (! strchr (buffer, ':')) continue;
  103.           
  104.           /* more or less no error-checking ;-)) */
  105.           strncpy (addr1, strtok (buffer, "."), 3);
  106.           strncpy (addr2, strtok (0, "."), 3);
  107.           strncpy (addr3, strtok (0, "."), 3);
  108.           strncpy (addr4, strtok (0, ":"), 3);
  109.  
  110.           ac.class_num = atoi (strtok (0, ":"));
  111.           ac.currently = 0;
  112.           ac.maximum = atoi (((cp = strtok (0, ":")), (cp && *cp) ? cp : "0"));
  113.           aa.hstart = atoi (((cp = strtok (0, ":")), (cp && *cp) ? cp : "0"));
  114.           aa.hend   = atoi (((cp = strtok (0, ":")), (cp && *cp) ? cp : "0"));
  115.           strncpy (ac.message,
  116.                (cp = strtok (0, "\n")) ? cp : "", MAX_MESSAGE-1);
  117.  
  118.           /* check whether this class is already defined */
  119.           for (i = 0; i < class_tab_index; i++)
  120.             if (class_tab[i].class_num == ac.class_num)
  121.               {
  122.             /* in this case just set a pointer to the defined class */
  123.             aa.ac = &class_tab[i];
  124.             break;
  125.               }
  126.  
  127.           /* if not, define it */
  128.           if (i == class_tab_index)
  129.             {
  130.               class_tab[class_tab_index] = ac;
  131.               if (++class_tab_index == class_tab_size)
  132.             {
  133.               class_tab_size <<= 1;
  134.               class_tab = (struct access_class *)
  135.                   realloc ((char *)class_tab,
  136.                        class_tab_size * sizeof (struct access_class));
  137.             }
  138.  
  139.               aa.ac = &class_tab[i];
  140.             }
  141.  
  142.           /* now set up the address, * maps into -1, anything else is vanilla */
  143.           aa.addr[0] = strcmp(addr1, "*") ? atoi (addr1) : -1;
  144.           aa.addr[1] = strcmp(addr2, "*") ? atoi (addr2) : -1;
  145.           aa.addr[2] = strcmp(addr3, "*") ? atoi (addr3) : -1;
  146.           aa.addr[3] = strcmp(addr4, "*") ? atoi (addr4) : -1;
  147.  
  148.           /* and add it to our address table */
  149.           addr_tab[addr_tab_index] = aa;
  150.           if (++addr_tab_index == addr_tab_size)
  151.             {
  152.               addr_tab_size <<= 1;
  153.               addr_tab = (struct access_address *)
  154.               realloc ((char *)addr_tab,
  155.                    addr_tab_size * sizeof (struct access_address));
  156.             }
  157.         } /* over total input */
  158.           fclose (in);
  159.           last_read = stb.st_mtime;
  160.           return;
  161.         } /* if open succeeded */
  162.     }
  163.     }
  164. }
  165.  
  166. /* the main function, validate an address (peer of given socket).
  167.  * return 0, if access is not permitted, else return a pointer to the
  168.  * corresponding class. Pass that pointer on logout to "release_host_access".
  169.  */
  170. struct access_class *
  171. allow_host_access (sockfd, outfd)
  172.      int sockfd, outfd;
  173. {
  174.   struct sockaddr_in apa;
  175.   int addr[4];
  176.   int len;
  177.   char *ipname;
  178.   struct access_address *ap;
  179.   int i;
  180. #define STRING(str) str,strlen(str)
  181.   
  182.   check_read_file (ACCESS_FILE);
  183.  
  184.   len = sizeof (apa);
  185.   if (getpeername (sockfd, (struct sockaddr *)&apa, &len) == -1)
  186.     {
  187.       perror ("getpeername");
  188.       write (outfd, STRING ("Sorry, internal game error.\n"));
  189.       return 0;
  190.     }
  191. #ifndef linux
  192.   ipname = inet_ntoa(ntohl(apa.sin_addr));
  193. #else
  194.   ipname = 0;
  195. #endif
  196.   sscanf (ipname, "%d.%d.%d.%d", addr, addr + 1, addr + 2, addr + 3);
  197.  
  198.   for (i = 0, ap = addr_tab; i < addr_tab_index; i++, ap++)
  199.     {
  200.       int pos;
  201.       /* check for address. match if either equal or wildcard */
  202.       for (pos = 0; pos < 4; pos++)
  203.     if (ap->addr[pos] != addr[pos] && ap->addr[pos] != -1) break;
  204.  
  205.       if (pos == 4) /* a match */
  206.     {
  207.       /* if hstart and hend are not == 0, check whether ap is in the
  208.        * interval */
  209.       if (ap->hstart || ap->hend)
  210.         {
  211.           time_t now = time(0);
  212.           struct tm *tm = localtime(&now);
  213.           if (ap->hstart < ap->hend)
  214.         {
  215.           if (tm->tm_hour < ap->hstart || tm->tm_hour > ap->hend)
  216.             continue;
  217.         }
  218.           else
  219.         {
  220.           if (tm->tm_hour > ap->hend && tm->tm_hour < ap->hstart)
  221.             continue;
  222.         }
  223.         }
  224.  
  225.       /* no maxmium? */
  226.       if (ap->ac->maximum == -1) 
  227.             { /*gc*/
  228.               log_access (ipname, 1);
  229.               return ap->ac;
  230.             }
  231.       /* else there is a maximum, in the worst case 0 */
  232.       if (ap->ac->currently >= ap->ac->maximum)
  233.         {
  234.           write (outfd, ap->ac->message, strlen (ap->ac->message));
  235.           write (outfd, "\n", 1);
  236.           shutdown (outfd, 2); close (outfd);
  237.           log_access (ipname, 0);
  238.           return 0;
  239.         }
  240.       /* bump up the counter */
  241.       ap->ac->currently ++;
  242.       log_access (ipname, 1);
  243.       return ap->ac;
  244.     }
  245.     }
  246.  
  247.   /* default is: don't allow access */
  248.   write (outfd, STRING("Sorry, you're not allowed to use LPMUD.\n"));
  249.   shutdown (outfd, 2); close (outfd);
  250.   log_access (ipname, 0);
  251.   return 0;
  252. }
  253.  
  254. /* decrement the currently counter once. This is called, when a user loggs out. */
  255.  
  256. void
  257. release_host_access (class)
  258.      struct access_class *class;
  259. {
  260.   if (class->maximum != -1 && class->currently > 0)
  261.     -- class->currently;
  262. }
  263.  
  264. static void
  265. log_access (addr, ok)
  266.      char *addr;
  267.      int ok;
  268. {
  269. #ifdef ACCESS_LOG
  270.   FILE *log = fopen (ACCESS_LOG, "a");
  271.  
  272.   if (log)
  273.     {
  274.       fprintf (log, "%s: %s\n", addr,  ok ? "granted" : "denied");
  275.       fclose (log);
  276.     }
  277. #endif
  278. }
  279.  
  280. #endif /* ACCESS_RESTRICTED */
  281.